case DOM0_GETDOMAININFO:
{
- struct task_struct *p;
+ struct task_struct *p = &idle0_task;
u_long flags;
- p = idle0_task.next_task;
read_lock_irqsave (&tasklist_lock, flags);
- do {
- if ((!is_idle_task (p)) && (p -> domain >= op.u.getdominfo.domain))
+
+ while ( (p = p->next_task) != &idle0_task )
+ if ( !is_idle_task(p) && (p->domain >= op.u.getdominfo.domain) )
break;
- } while ((p = p -> next_task) != &idle0_task);
- ret = -ESRCH;
- if ( p != &idle0_task )
+ if ( p == &idle0_task )
+ {
+ ret = -ESRCH;
+ }
+ else
{
op.u.getdominfo.domain = p->domain;
strcpy (op.u.getdominfo.name, p->name);
unsigned char *end; /* End pointer */
void (*destructor)(struct sk_buff *); /* Destruct function */
- struct pfn_info *pf; /* record of physical pf address for freeing */
- net_vif_t *src_vif; /* vif we came from */
- net_vif_t *dst_vif; /* vif we are bound for */
- struct skb_shared_info shinfo; /* shared info is no longer shared in Xen. */
+
+ unsigned short guest_id; /* guest-OS's id for this packet (tx only!) */
+ struct pfn_info *pf; /* record of physical pf address for freeing */
+ net_vif_t *src_vif; /* vif we came from */
+ net_vif_t *dst_vif; /* vif we are bound for */
+ struct skb_shared_info shinfo; /* shared info not shared in Xen. */
};
extern void __kfree_skb(struct sk_buff *skb);
if ( ntohs(skb->mac.ethernet->h_proto) == ETH_P_ARP )
memcpy(skb->nh.raw + 18, vif->vmac, ETH_ALEN);
+ /*
+ * Slightly gross: we need the page_lock so that we can do PTE checking.
+ * However, we take it slightly early so that it can protect the update
+ * of rx_cons. This saves us from grabbing two locks.
+ */
+ spin_lock(&vif->domain->page_lock);
+
if ( (i = vif->rx_cons) == vif->rx_prod )
+ {
+ spin_unlock(&vif->domain->page_lock);
return;
-
+ }
rx = vif->rx_shadow_ring + i;
+ vif->rx_cons = RX_RING_INC(i);
size = (unsigned short)skb->len;
offset = (unsigned char)((unsigned long)skb->data & ~PAGE_MASK);
- spin_lock(&vif->domain->page_lock);
-
/* Release the page-table page. */
pte_page = frame_table + (rx->pte_ptr >> PAGE_SHIFT);
put_page_type(pte_page);
/* Bail out if the PTE has been reused under our feet. */
list_add(&old_page->list, &vif->domain->pg_head);
old_page->flags = vif->domain->domain;
+ unmap_domain_mem(ptep);
+ spin_unlock(&vif->domain->page_lock);
status = RING_STATUS_BAD_PAGE;
goto out;
}
* NB. The remote flush here should be safe, as we hold no locks. The
* network driver that called us should also have no nasty locks.
*/
- rx = vif->rx_shadow_ring + vif->rx_cons;
if ( rx->flush_count == (unsigned short)
atomic_read(&tlb_flush_count[vif->domain->processor]) )
flush_tlb_cpu(vif->domain->processor);
out:
- vif->rx_cons = RX_RING_INC(vif->rx_cons);
make_rx_response(vif, rx->id, size, status, offset);
}
{
int i;
net_vif_t *vif = skb->src_vif;
- tx_shadow_entry_t *tx;
unsigned long flags;
spin_lock_irqsave(&vif->domain->page_lock, flags);
skb_shinfo(skb)->nr_frags = 0;
- tx = vif->tx_shadow_ring + vif->tx_cons;
- vif->tx_cons = TX_RING_INC(vif->tx_cons);
- make_tx_response(vif, tx->id, RING_STATUS_OK);
+ make_tx_response(vif, skb->guest_id, RING_STATUS_OK);
put_vif(vif);
}
vif = list_entry(ent, net_vif_t, list);
get_vif(vif);
remove_from_net_schedule_list(vif);
- if ( vif->tx_idx == vif->tx_prod )
+ if ( vif->tx_cons == vif->tx_prod )
{
put_vif(vif);
continue;
}
/* Pick an entry from the transmit queue. */
- tx = &vif->tx_shadow_ring[vif->tx_idx];
- vif->tx_idx = TX_RING_INC(vif->tx_idx);
- if ( vif->tx_idx != vif->tx_prod )
+ tx = &vif->tx_shadow_ring[vif->tx_cons];
+ vif->tx_cons = TX_RING_INC(vif->tx_cons);
+ if ( vif->tx_cons != vif->tx_prod )
add_to_net_schedule_list_tail(vif);
skb->destructor = tx_skb_release;
skb->src_vif = vif;
skb->dst_vif = NULL;
skb->mac.raw = skb->data;
+ skb->guest_id = tx->id;
skb_shinfo(skb)->frags[0].page = frame_table +
(tx->payload >> PAGE_SHIFT);